const os = require('os');
const fs = require('fs');
const xmlbuilder = require('xmlbuilder');

const makeJUnitOutput = async (results, outputPath) => {
  const output = {
    testsuites: {
      testsuite: []
    }
  };

  results.forEach((result) => {
    const assertionTestCount = result.assertionResults ? result.assertionResults.length : 0;
    const preRequestTestCount = result.preRequestTestResults ? result.preRequestTestResults.length : 0;
    const testCount = result.testResults ? result.testResults.length : 0;
    const postResponseTestCount = result.postResponseTestResults ? result.postResponseTestResults.length : 0;
    const totalTests = assertionTestCount + preRequestTestCount + testCount + postResponseTestCount;

    const suite = {
      '@name': result.name,
      '@errors': 0,
      '@failures': 0,
      '@skipped': 0,
      '@tests': totalTests,
      '@timestamp': new Date().toISOString().split('Z')[0],
      '@hostname': os.hostname(),
      '@time': result.runDuration.toFixed(3),
      'testcase': []
    };

    result.assertionResults
    && result.assertionResults.forEach((assertion) => {
      const testcase = {
        '@name': `${assertion.lhsExpr} ${assertion.rhsExpr}`,
        '@status': assertion.status,
        '@classname': result.request.url,
        '@time': (result.runDuration / totalTests).toFixed(3)
      };

      if (assertion.status === 'fail') {
        suite['@failures']++;

        testcase.failure = [{ '@type': 'failure', '@message': assertion.error }];
      }

      suite.testcase.push(testcase);
    });

    result.preRequestTestResults
    && result.preRequestTestResults.forEach((test) => {
      const testcase = {
        '@name': test.description,
        '@status': test.status,
        '@classname': result.request.url,
        '@time': (result.runDuration / totalTests).toFixed(3)
      };

      if (test.status === 'fail') {
        suite['@failures']++;

        testcase.failure = [{ '@type': 'failure', '@message': test.error }];
      }

      suite.testcase.push(testcase);
    });

    result.testResults
    && result.testResults.forEach((test) => {
      const testcase = {
        '@name': test.description,
        '@status': test.status,
        '@classname': result.request.url,
        '@time': (result.runDuration / totalTests).toFixed(3)
      };

      if (test.status === 'fail') {
        suite['@failures']++;

        testcase.failure = [{ '@type': 'failure', '@message': test.error }];
      }

      suite.testcase.push(testcase);
    });

    result.postResponseTestResults
    && result.postResponseTestResults.forEach((test) => {
      const testcase = {
        '@name': test.description,
        '@status': test.status,
        '@classname': result.request.url,
        '@time': (result.runDuration / totalTests).toFixed(3)
      };

      if (test.status === 'fail') {
        suite['@failures']++;

        testcase.failure = [{ '@type': 'failure', '@message': test.error }];
      }

      suite.testcase.push(testcase);
    });

    if (result?.skipped) {
      suite['@skipped'] = 1;
    } else if (result.error) {
      suite['@errors'] = 1;
      suite['@tests'] = 1;
      suite.testcase = [
        {
          '@name': 'Test suite has no errors',
          '@status': 'fail',
          '@classname': result.request.url,
          '@time': result.runDuration.toFixed(3),
          'error': [{ '@type': 'error', '@message': result.error }]
        }
      ];
    }

    output.testsuites.testsuite.push(suite);
  });

  fs.writeFileSync(outputPath, xmlbuilder.create(output).end({ pretty: true }));
};

module.exports = makeJUnitOutput;
